package com.foruo.simple.rpc.consumer;

import com.foruo.simple.rpc.entity.DemoEntity;
import com.foruo.simple.rpc.service.IDemoService;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Proxy;
import java.net.Socket;

/**
 * 消费者 - 使用远程接口
 * @author GaoYuan
 * @date 2018/9/26 下午7:29
 */
public class ConsumerStarter {

    public static void main(String[] args){
        // 这里实际上相当于获取了IDemoService的实现
        IDemoService demoService = (IDemoService)simpleRpc(IDemoService.class);
        // 执行getDemo方法时，相当于调用了代理的处理方法
        DemoEntity demoEntity = demoService.getDemo("1");
        System.out.println(demoEntity.getName());
    }

    /**
     * 远程调用具体代码
     * @author GaoYuan
     */
    public static Object simpleRpc(Class myClass){
        return Proxy.newProxyInstance(myClass.getClassLoader(), new Class[]{myClass}, (proxy, method, args) -> {
            // socket连接8080端口
            Socket socket = new Socket("127.0.0.1", 8989);

            // 获取类名 （这里是获取 IDemoService 接口名）
            String className = myClass.getName();
            // 获取方法名
            String methodName = method.getName();
            // 获取方法参数
            Class[] methodParameterTypes = method.getParameterTypes();

            /**
             * 这里主要将 需要调用的目标方法（包含对象类名/接口名）以socket形式传递过去，以调用远程接口
             * 就是告诉远程接口，我想要调用什么方法
             * */
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeUTF(className);
            System.out.println(">>>>>> [发送]：" + className);
            objectOutputStream.writeUTF(methodName);
            System.out.println(">>>>>> [发送]：" + methodName);
            objectOutputStream.writeObject(methodParameterTypes);
            System.out.println(">>>>>> [发送]：" + methodParameterTypes);
            objectOutputStream.writeObject(args);
            System.out.println(">>>>>> [发送]：" + args);
            objectOutputStream.flush();

            /** 获取远程接口执行结果 */
            ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
            Object o = objectInputStream.readObject();
            System.out.println(">>>>>> [接收]：" + o);
            // 关闭流
            objectInputStream.close();
            objectOutputStream.close();
            // 关闭socket
            socket.close();

            return o;
        });
    }

}
